package org.framework.converter;

import com.fasterxml.jackson.core.json.PackageVersion;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.stream.Collectors;

public class EnumBaseModule extends SimpleModule {

    static final String DEFAULT_RESOURCE_PATTERN = "**/*.class";

    private static String resourcePattern = DEFAULT_RESOURCE_PATTERN;

    private static ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();

    private static MetadataReaderFactory metadataReaderFactory = new CachingMetadataReaderFactory();


    public EnumBaseModule(String[] packageNameArray) {
        super(PackageVersion.VERSION);
        if(packageNameArray !=null && packageNameArray.length >0){
            // 找到EnumBase接口所在的包下所有实现该接口的枚举类
            Set<Class> set = getEnumClassesByInterface(packageNameArray,EnumBase.class).stream().collect(Collectors.toSet());

            // 动态注册所有实现了EnumBase接口枚举类的序列化器和反序列化器到Jackson
            set.forEach(enumClass -> {
                addSerializer(enumClass, new EnumBaseSerializer());
                addDeserializer(enumClass,new EnumBaseDeserializer());
            });
        }
    }



    public static Set<Class<?>> getEnumClassesByInterface(String[] packageNameArray, Class<EnumBase> c) {
        // 第一个class类的集合
        Set<Class<?>> classes = new LinkedHashSet<Class<?>>();
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        try {
            // 获取包的名字 并进行替换
            for (String packageName : packageNameArray) {
                String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
                        packageName + '/';
                String packageDirName = packageSearchPath.replace('.', '/')+ resourcePattern;
                Resource[] resources = resourcePatternResolver.getResources(packageDirName);
                for (Resource resource : resources) {
                    if (resource.isReadable()) {
                        MetadataReader metadataReader = metadataReaderFactory.getMetadataReader(resource);
                        ClassMetadata classMetadata = metadataReader.getClassMetadata();
                        if(classMetadata.isIndependent() && classMetadata.isConcrete()){
                            Class<?> targerClass = Class.forName(classMetadata.getClassName(),true,contextClassLoader);
                            if(targerClass.isEnum()&& EnumBase.class.isAssignableFrom(c)){
                                classes.add(targerClass);
                            }
                        }
                    }
                }
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        return  classes;

    }
}